package middleware

import (
	"ginblog/utils"
	"ginblog/utils/errmsg"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"
	"strings"
	"time"
)

var JwtKey = []byte(utils.JwtKey)
var code int

type MyClaims struct {
	Username string `json:"username"`
	jwt.StandardClaims
}

// 生成token
func SetToken(username string) (string,int) {
	expireTime := time.Now().Add(10 * time.Hour)	//过期时间10小时
	setClaim := MyClaims{
		Username: username,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expireTime.Unix(),	//过期时间（时间戳）
			Issuer: "ginblog",	//发行者
		},
	}

	reqClaim := jwt.NewWithClaims(jwt.SigningMethodHS256,setClaim)	//生成token
	token,err := reqClaim.SignedString(JwtKey)	//转换为字符串
	if err != nil {
		return "",errmsg.ERROR
	}
	return token,errmsg.SUCCSE
}

// 验证token
func CheckToken(token string) (*MyClaims,int) {
	setToken,_ := jwt.ParseWithClaims(token,&MyClaims{}, func(token *jwt.Token) (interface{}, error) {
		return JwtKey,nil
	})

	if key,_ := setToken.Claims.(*MyClaims); setToken.Valid {
		return key,errmsg.SUCCSE
	}else {
		return nil,errmsg.ERROR
	}

}


//jwt中间件
func JwtToken() gin.HandlerFunc {
	return func(c *gin.Context) {
		tokenHeader := c.Request.Header.Get("Authorization")
		if tokenHeader == "" {
			code = errmsg.ERROR_TOKEN_NOT_EXIST		//token不存在
			c.JSON(http.StatusOK,gin.H{
				"code":code,
				"message":errmsg.GetErrmsg(code),
			})
			c.Abort()
			return
		}
		checkToken := strings.SplitN(tokenHeader," ",2)
		if len(checkToken) != 2 && checkToken[0] != "Bearer" {
			code = errmsg.ERROR_TOKEN_TYPE_WRONG	//token字符串格式错误
			c.JSON(http.StatusOK,gin.H{
				"code":code,
				"message":errmsg.GetErrmsg(code),
			})
			c.Abort()
			return
		}
		key, tCode := CheckToken(checkToken[1])
		if tCode == errmsg.ERROR {
			code = errmsg.ERROR_TOKEN_WRONG		//token验证失败
			c.JSON(http.StatusOK,gin.H{
				"code":code,
				"message":errmsg.GetErrmsg(code),
			})
			c.Abort()
			return
		}
		if time.Now().Unix() > key.ExpiresAt {
			code = errmsg.ERROR_TOKEN_RUNTIME
			c.JSON(http.StatusOK,gin.H{
				"code":code,
				"message":errmsg.GetErrmsg(code),
			})
			c.Abort()
			return
		}

		c.Set("username",key.Username)
		c.Next()
	}
}
